package com.example.javamaday.graph;

import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 广度优先搜索（无向图）
 */
public class BreadthFirstSearch {

    private int count;  // 记录当前有多少个个顶点与s顶点相通
    private boolean[] marked;  //索引代表顶点，值表示当前顶点是否已经被搜索

    private ConcurrentLinkedQueue<Integer> waitSearch;

    // 构造广度优先搜索对象，使用广度优先搜索找出G图中s顶点的所有相邻顶点
    public BreadthFirstSearch(Graph g, int s) {
        this.marked = new boolean[g.V()];
        this.count = 0;  // 搜索之前设置为0
        this.waitSearch = new ConcurrentLinkedQueue<>();
        bfs(g, s);
    }

    // 使用广度优先搜索找出G图中v顶点的所有相通的顶点
    private void bfs(Graph g, int v) {
        // 设置当前顶点已经搜索
        System.out.println(v);
        marked[v] = true;
        waitSearch.add(v);
        while (!waitSearch.isEmpty()) {
            Integer wait = waitSearch.poll();
            for(Integer w : g.adj(wait)) {
                if (!marked[w]) {
                    System.out.println(w);
                    marked[w] = true;
                    waitSearch.add(w);
                }
            }
        }
        // 相通顶点数+1
        count++;
    }

    // 判断w顶点与s顶点是否相通
    public boolean marked(int w) {
        return marked[w];  // 是否被搜索过 即 是否相通
    }

    // 获取与顶点相通的所有顶点的个数
    public int count() {
        return count;
    }

    public static void main(String[] args) {
        // 准备一幅图
        Graph graph = new Graph(13);
        graph.addEdge(0, 5);
        graph.addEdge(0, 1);
        graph.addEdge(0, 2);
        graph.addEdge(0, 6);
        graph.addEdge(5, 3);
        graph.addEdge(5, 4);
        graph.addEdge(3, 4);
        graph.addEdge(4, 6);

        graph.addEdge(7, 8);

        graph.addEdge(9, 11);
        graph.addEdge(9, 10);
        graph.addEdge(9, 12);
        graph.addEdge(11, 12);
        // 准备广度优先搜索对象
        BreadthFirstSearch search = new BreadthFirstSearch(graph, 0);

        // 测试与某个顶点相通的顶点数量
        int count = search.count();
        System.out.println("与顶点0相通的个数为：" + count);
        // 测试某个顶点与起点是否相通
        System.out.println("5和0是否相通：" + search.marked(5));
        System.out.println("7和0是否相通：" + search.marked(7));
    }

}
